package juc.popular;

import java.util.Collection;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * {@link ArrayBlockingQueue} 是数组实现的线程安全的有界的阻塞队列
 * ReentrantLock 实现
 * <p>
 * * 构造方法
 * * * {@link ArrayBlockingQueue#ArrayBlockingQueue(int)}           传入初始容量,默认非公平锁去实现入队和出队
 * * * {@link ArrayBlockingQueue#ArrayBlockingQueue(int, boolean)}  传入初始容量,可自定义锁的类型
 * * * {@link ArrayBlockingQueue#ArrayBlockingQueue(int, boolean, Collection)}
 * <p>
 * * * {@link ArrayBlockingQueue#add(Object)}                       入队,队列满了会报错
 * * * {@link ArrayBlockingQueue#offer(Object)}                     入队,队列满了会返回false
 * * * {@link ArrayBlockingQueue#offer(Object, long, TimeUnit)}     入队,可以设置等待时间，队列满了会返回false
 * * * {@link ArrayBlockingQueue#put(Object)}                       入队,队列满了会阻塞
 * <p>
 * * * {@link ArrayBlockingQueue#peek()}                            获取队列头部元素，为空会返回null
 * * * {@link ArrayBlockingQueue#element()}                         获取队列头部元素，为空会会报错
 * <p>
 * * * {@link ArrayBlockingQueue#poll()}                            出队,队列为空会返回null
 * * * {@link ArrayBlockingQueue#poll(long, TimeUnit)}              出队,队列为空会报错
 * * * {@link ArrayBlockingQueue#remove()}                          出队,队列为空会报错
 * * * {@link ArrayBlockingQueue#take()}                            出队,队列为空会阻塞
 * *
 *
 * @author 王霄
 * @date 2021/9/24 16:00
 **/
public class ArrayBlockingQueueDemo {

    public static void main(String[] args) {
        ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
        new Out("out", queue).start();
        new In("in", queue).start();
    }

    public static class Out extends Thread {
        private final ArrayBlockingQueue<Integer> queue;

        public Out(String name, ArrayBlockingQueue<Integer> queue) {
            super(name);
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    queue.put(new Random().nextInt(10));
                    System.out.println(getName() + ": " + queue);
                }
            } catch (InterruptedException ignored) {
            }
        }
    }

    public static class In extends Thread {
        private final ArrayBlockingQueue<Integer> queue;

        public In(String name, ArrayBlockingQueue<Integer> queue) {
            super(name);
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    queue.take();
                    System.out.println(getName() + ": " + queue);
                    TimeUnit.SECONDS.sleep(2);
                }
            } catch (InterruptedException ignored) {
            }
        }
    }
}
